/**
 * 画圆
 */
import L from "leaflet";

class CircleSelect {
  constructor(map, options) {
    Object.assign(this, {
      startPoint: null,
      endPoint: null,
      circle: null,
      layer: L.layerGroup(),
      color: "#32CEFF",
      map: null,
      parent: null,
      clickCount: 0,
      radius: null,
      radiusM: null,
      opacity: 1,
      fillOpacity: 0.6,
      draggable: true,
      tempLines: L.polyline([], { dashArray: 5 }),
      tooltip: null,
      redPt: null,
      cancelMarker: null,
      isFixRadius: false,
      radar: null,
      timeStep: null,
      isShowRader: false, // 是否显示雷达动效
      animateCircle: null,
      timerList: [],
      radarShodow: null, // 雷达里的阴影
      callback: null,
      id: null,
      bShowTooltip: false,
      bStartDrag: false,
      bDragReady: true,
      needDefaultRadius: false, // true 有默认半径
      needFitBounds: true,
      needRedPt: false,
      maxArea: null, // 限制最大的面积，不能超过它
      ...options,
    });
    this.init(map);
  }
  init(map) {
    this.map = map;
    this.parent = {};
  }
  startDraw({ callback, mouseMoveCallback }) {
    if (this.map) {
      if (this.clickCount > 0) {
        this.clear();
      }
      this.callback = callback;
      this.mouseMoveCallback = mouseMoveCallback;
      this.map.on("mousedown", this.mousedown);
    } else {
      console.log("circle对象未获取到map");
    }
  }
  addCircle() {
    const radius = this.getRadius();
    console.log("circle drawing", radius);
    this.radiusM = radius.toFixed(2);
    let _color = this.color,
      _fillOpacity = this.fillOpacity;
    if (!this.circle) {
      this.circle = L.circle(this.startPoint, radius, {
        color: _color,
        fillColor: _color,
        fillOpacity: _fillOpacity,
        opacity: this.opacity,
        weight: 2,
      }).addTo(this.map);
    } else {
      this.circle.setRadius(radius);
    }
    this.circle.on("click", () => {
      if (this.saveTooltip) {
        this.saveTooltip.addTo(this.map);
        this.setClickEvent(this.saveTooltip);
      }
    });
    if (this.clickCount > 1 || this.draggable) {
      this.addCancelBtn();
    }
  }
  getRadius() {
    let center = this.startPoint;
    let end = this.endPoint;
    const dx = center.lng - end.lng;
    const dy = center.lat - end.lat;
    let radius = dx * dx + dy * dy;
    this.radius = Math.sqrt(radius);
    radius = L.latLng(center.lat, center.lng).distanceTo(
      L.latLng(end.lat, end.lng)
    );
    return radius;
  }
  setId() {
    this.id = "circle_" + new Date().getTime();
  }
  setTooltip() {
    if (!this.bShowTooltip || !this.circle) return;
    const { preventCircleMap, currentEditPreventId } = this.parent;
    const map = preventCircleMap.get(currentEditPreventId);
    map && map.eachLayer((item) => item._icon && item.closePopup());

    this.saveTooltip && this.map.removeLayer(this.saveTooltip);
    let selectedValue = "0";
    if (this.circle && this.circle.typeObj) {
      selectedValue = this.circle.typeObj.value;
    } else if (this.properties && this.properties.typeObj) {
      selectedValue = this.properties.typeObj.value;
    }
    const tooltip = L.tooltip({
      direction: "top",
      permanent: false,
      interactive: true,
      noWrap: true,
      opacity: 0.9,
    });
    const content = `<div class="preventCircle-polygon">
                      <select>
                        <option value="0" ${
                          selectedValue === "0" ? "selected" : ""
                        }>核心管控区</option>
                        <option value="1" ${
                          selectedValue === "1" ? "selected" : ""
                        }>重点控制区</option>
                        <option value="2" ${
                          selectedValue === "2" ? "selected" : ""
                        }>关注分流区</option>
                      </select>
                      <span class="preventCircle-polygon-btn">保存</span>
                    </div>`;
    tooltip.setContent(content);
    const lat = this.circle.getBounds().getNorth();
    const lng = this.startPoint.lng;
    tooltip.setLatLng([lat, lng]);
    tooltip.addTo(this.map);
    this.setClickEvent(tooltip);
    this.saveTooltip = tooltip;
  }
  dragEndHander() {
    this.setTooltip();
    this.showTooltip();
    this.parent.savePrevent &&
      this.parent.savePrevent(this.parent.currentEditPreventType, false);

    this.timerDragReaday && clearTimeout(this.timerDragReaday);
    this.timerDragReaday = setTimeout(() => (this.bDragReady = true), 200);
    if (this.isShowRader) {
      this.createRadarAnimate();
    }
  }
  showTooltip() {
    if (this.circle) {
      const lat = this.circle.getBounds().getNorth();
      const lng = this.startPoint.lng;
      this.saveTooltip && this.saveTooltip.setLatLng([lat, lng]);
    }
  }
  hideTooltip() {
    this.saveTooltip && this.map.removeLayer(this.saveTooltip);
  }
  setClickEvent(tooltip) {
    const el = tooltip.getElement();
    el.addEventListener("click", (e) => L.DomEvent.stopPropagation(e));
    const bntSpan = el.getElementsByClassName("preventCircle-polygon-btn")[0];
    bntSpan.removeEventListener("click", this.savePrevent);
    bntSpan.addEventListener("click", this.savePrevent);
    el.style.pointerEvents = "auto";
  }
  savePrevent = (e) => {
    L.DomEvent.stopPropagation(e); //阻止事件往map方向冒泡
    const parent = document.getElementsByClassName("preventCircle-polygon");
    if (parent.length > 0) {
      const child = parent[0].getElementsByTagName("select");
      if (child.length > 0) {
        const value = child[0].value;
        const text = child[0].selectedOptions[0].text;
        this.circle.typeObj = { value, text };
      }
    }
    this.select();
    // this.map.removeLayer(this.saveTooltip);
    this.parent.savePrevent(this.parent.currentEditPreventType, false);
    this.hideTooltip();
    // this.parent.bSavePrevent = false;
  };
  clear() {
    this.close();
    this.redPt && this.map.removeLayer(this.redPt);
  }
  close() {
    this.layer.clearLayers();
    this.radius = null;
    this.tooltip && this.tooltip.remove();
    this.parent &&
      this.parent.setState &&
      this.parent.setState({ draggedCircle: [-30, -120] });
    this.clearEvent();
    this.cancelMarker && this.map.removeLayer(this.cancelMarker);
    this.cancelMarker = null;
    this.circle && this.map.removeLayer(this.circle);
    this.circle = null;
    this.radarShodow && this.map.removeLayer(this.radarShodow);
    this.radarShodowInset && this.map.removeLayer(this.radarShodowInset);
    this.dragMarker && this.map.removeLayer(this.dragMarker);
    this.saveTooltip && this.map.removeLayer(this.saveTooltip);
    this.clickCount = 0;
  }
  clearEvent() {
    this.map
      .off("mousedown", this.mousedown)
      .off("mouseup", this.mouseup)
      .off("mousemove", this.mousemove);
  }
  mousedown = (e) => {
    console.log(this, "mousedown");
    L.DomEvent.stopPropagation(e); // 阻止事件往map方向冒泡
    const _this = this;
    if (_this.clickCount > 0) return;
    _this.clickCount++;
    _this.circle = null;
    _this.map.dragging.disable();
    if (_this.clickCount == 1) {
      _this.startPoint = e.latlng;
      if (_this.needRedPt) {
        _this.redPt = L.circle(e.latlng, 1, {
          color: "#ff0000",
          fillColor: "ff0000",
          fillOpacity: 1,
        });
        _this.map.addLayer(_this.redPt);
      }
    }
    if (_this.isFixRadius && _this.radius == null) {
      let i = 0;
      while (i < 20) {
        ((_i) => {
          // eslint-disable-line no-loop-func
          setTimeout(
            () => {
              _this.timeStep = i;
              _this.endPoint = _this.getEndPoint(
                _this.startPoint,
                (1000 * (_i + 1)) / 20
              );
              _this.addCircle();
              if (_i == 19) {
                _this.createRadarAnimate();
                _this.select();
              }
            },
            (1000 * (i + 1)) / 60
          );
        })(i);
        i++;
      }

      _this.map.off("mouseup", _this.mouseup).off("mousedown", _this.mousedown);
    } else {
      _this.map.on("mousemove", _this.mousemove);
    }
    _this.map.on("mouseup", _this.mouseup);
    if (_this.clickCount == 2) {
      // _this.addCircle();
    }
  };
  mousemove = (e) => {
    const _this = this;
    // if (!_this.startPoint) return;
    const endPointBak = _this.endPoint;
    _this.endPoint = e.latlng;
    const radius = _this.getRadius();
    const area = Math.PI * radius * radius;

    if (!this.maxArea || area < this.maxArea) {
      _this.addCircle();
      // const radius = _this.getRadius();
      const radiusM = radius.toFixed(2);
      const { lng, lat } = _this.startPoint;
      const { lng: endLng, lat: endLat } = _this.endPoint;
      this.circle.id = _this.id;
      if (this.mouseMoveCallback) {
        this.mouseMoveCallback({
          lng,
          lat,
          endLng,
          endLat,
          radius: radiusM,
          circle: _this.circle,
        });
      }
      _this.map.on("mouseup", _this.mouseup);
    } else {
      _this.endPoint = endPointBak;
    }
  };
  mouseup = () => {
    if (this.endPoint || 1 < 2) {
      this.map.dragging.enable();

      if (!this.isFixRadius) {
        this.select();
      }
      if (this.radius == null && this.needDefaultRadius) {
        let i = 0;
        while (i < 20) {
          ((_i) => {
            // eslint-disable-line no-loop-func
            setTimeout(
              () => {
                this.timeStep = i;
                this.endPoint = this.getEndPoint(
                  this.startPoint,
                  (1000 * (_i + 1)) / 20
                );
                this.addCircle();
                if (_i == 19) {
                  this.createRadarAnimate();
                  this.select();
                }
              },
              (1000 * (i + 1)) / 60
            );
          })(i);
          i++;
        }
      }
      this.map
        .off("mousemove", this.mousemove)
        .off("mouseup", this.mouseup)
        .off("mousedown", this.mousedown);
      this.dragEndHander();
    } else {
      this.map.on("mousemove", this.mousemove);
    }
  };
  mousemoveHandler = (e) => {
    if (this.bStartDrag) {
      const radius = this.getRadius();
      this.circle.setLatLng(e.latlng);
      this.startPoint = e.latlng;
      this.endPoint = this.getEndPoint(this.startPoint, radius);
      this.addCircle();
    }
    // this.showTooltip();
  };
  mouseupHandler = () => {
    if (this.bStartDrag) {
      this.setMapState(true);
      this.dragEndHander();
      this.map.removeEventListener("mousemove");
      this.map.dragging.enable();
      this.bStartDrag = false;
      this.bDragReady = false;
    }
  };
  getEndPoint(startPoint, radius = 1000) {
    const d = this.meter2degree(radius);
    let lng = startPoint.lng + d;
    const { lat } = startPoint;

    let dist = startPoint.distanceTo(L.latLng(lat, lng));
    while (dist > radius + 0.1) {
      lng -= 0.00001;
      dist = startPoint.distanceTo(L.latLng(lat, lng));
    }

    while (dist < radius - 0.1) {
      lng += 0.00001;
      dist = startPoint.distanceTo(L.latLng(lat, lng));
    }
    return { lat, lng };
  }
  get45Point(startPoint, endPoint, radius = 1000) {
    if (endPoint) {
      radius = startPoint.distanceTo(endPoint);
    }
    const d = this.meter2degree(radius);
    let lng = startPoint.lng + d;
    let lat = startPoint.lat + d / 11;

    let dist = startPoint.distanceTo(L.latLng(lat, lng));
    while (dist > radius + 0.1) {
      lng -= 0.00001;
      lat -= 0.00001;
      dist = startPoint.distanceTo(L.latLng(lat, lng));
    }

    while (dist < radius - 0.1) {
      lng += 0.00001;
      lat += 0.00001;
      dist = startPoint.distanceTo(L.latLng(lat, lng));
    }
    return { lat, lng };
  }
  meter2degree(dist) {
    return (dist / (6378137 * Math.PI * 2)) * 360;
  }
  degree2meter(dist) {
    return (dist * 6378137 * Math.PI * 2) / 360;
  }
  addCancelBtn() {
    if (!this.bShowEditBtn) return;
    let latlng;
    if (this.draggable) {
      const rst = this.get45Point(this.startPoint, this.endPoint, 1000);
      latlng = new L.LatLng(rst.lat, rst.lng);
    } else {
      latlng = new L.LatLng(this.endPoint.lat, this.endPoint.lng);
    }
    const icon = ICONS.deleteIcon;
    this.cancelMarker && this.map.removeLayer(this.cancelMarker);
    this.cancelMarker = L.marker(latlng, { icon, title: "清除" })
      .addTo(this.map)
      .on("click", () => {
        this.deleteCallback && this.deleteCallback(this);
        // this.select(true);
        this.parent.savePrevent &&
          this.parent.savePrevent(this.parent.currentEditPreventType, false);
        this.clear();
        this.parent.doNotifyClearSelect && this.parent.doNotifyClearSelect();
      });
  }
  select(isEdit = false, isClear = false) {
    if (!this.endPoint || Number(this.radiusM) < 1) {
      this.clear();
      return;
    }
    const radius = this.getRadius();
    const radiusM = radius.toFixed(2);
    const { lng, lat } = this.startPoint;
    const { lng: endLng, lat: endLat } = this.endPoint;
    this.circle.id = this.id;
    const rst = this.get45Point(this.startPoint, this.endPoint, 1000);
    // console.log(lng, lat, rst.lng, rst.lat, radiusM);
    if (this.parent?.doCircleSelect) {
      this.parent.doCircleSelect({
        lng,
        lat,
        radius,
        circle: this.circle,
        isClear,
      });
    }
    if (this.callback) {
      this.callback({
        lng,
        lat,
        endLng,
        endLat,
        delEndlng: rst.lng,
        delEndlat: rst.lat,
        radius: radiusM,
        circle: this.circle,
        isEdit: isEdit,
      });
    }
  }
  /**
   * 调整地图范围，看得清楚整个圆
   */
  fitBounds() {
    this.map.fitBounds(this.circle.getBounds());
  }
}

export default CircleSelect;
